﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Invoicing.Model.Accounts;

namespace Invoicing.Command.Accounts
{
    public class UserCommand
    {
        public static void SaveCheck(UserModel user, DBCentre db)
        {
            if (string.IsNullOrEmpty(user.UserName))
                throw new ApplicationException("请提供用户名");
          
            if (user.ID == 0)
            {
                if (string.IsNullOrEmpty(user.Password))
                    throw new ApplicationException("请提供用户密码");
            }
            else
            {

            }
            if (user.Roles==null || user.Roles.Count==0)
                throw new ApplicationException("请提供用户角色");
            if (db != null)
            {
                if (db.DataContext.Users.Any(p=>p.UserName==user.UserName && p.ID!=user.ID))
                    throw new ApplicationException("用户名重复 ");
            }
        }

        public static UserModel CreateNewUser(UserModel user)
        {
            if (user != null)
            {
                user.CreatedOn = DateTime.Now;
                user.Guid = Guid.NewGuid().ToString();
                using (DBCentre db = new DBCentre())
                {
                    SaveCheck(user, db);
                    var dUser = Convertor.ConvertFrom<User, UserModel>(user);
                    var rids = user.Roles.Select(p => p.ID).ToArray();
                    var roles = db.DataContext.Roles.Where(p => rids.Contains(p.ID)).ToList();
                    dUser.Roles = roles;
                    db.DataContext.Users.Add(dUser);
                    db.DataContext.SaveChanges();
                    user.ID = dUser.ID;
                    return user;
                }
            }
            return null;
        }

        public static void UpdateUser(UserModel user)
        {
            if (user != null && user.ID > 0)
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.ID == user.ID);
                    if (dUser != null)
                    {
                        SaveCheck(user, db);
                        if (string.IsNullOrEmpty(user.Password))
                            user.Password = dUser.Password;
                        Convertor.UpdateValue(user, dUser);
                        dUser.Roles.Clear();
                        var rids = user.Roles.Select(p => p.ID).ToArray();
                        var roles = db.DataContext.Roles.Where(p => rids.Contains(p.ID)).ToList();
                        dUser.Roles = roles;
                        db.DataContext.SaveChanges();
                    }
                    else
                        throw new ApplicationException("不存在的用户");
                }
            }
        }

        public static void DeleteUser(int id)
        {
            if (id > 0)
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.ID == id);
                    if (dUser != null)
                    {
                        if (dUser.Roles.Any(p => p.RoleName == "Admin"))
                            throw new ApplicationException("不删除系统管理员");
                        db.DataContext.Users.Remove(dUser);
                        db.DataContext.SaveChanges();
                    }
                }
            }
        }

        public static UserModel GetUser(string guid)
        {
            if (!string.IsNullOrEmpty(guid))
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.Guid == guid);
                    if (dUser != null)
                    {
                        var user = Convertor.ConvertTo<UserModel, User>(dUser);
                        user.Roles = Convertor.ConvertCollection<RoleModel, Role, RoleCollection>(dUser.Roles);
                        return user;
                    }
                }
            }
            return null;
        }
        public static UserModel GetUserByUserName(string username)
        {
            if (!string.IsNullOrEmpty(username))
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.UserName == username);
                    if (dUser != null)
                    {
                        var user = Convertor.ConvertTo<UserModel, User>(dUser);
                        return user;
                    }
                }
            }
            return null;
        }
        public static UserModel GetUser(int id)
        {
            if (id>0)
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.ID==id);
                    if (dUser != null)
                    {
                        var user = Convertor.ConvertTo<UserModel, User>(dUser);
                        user.Roles = Convertor.ConvertCollection<RoleModel, Role, RoleCollection>(dUser.Roles);
                        return user;
                    }
                }
            }
            return null;
        }

        public static UserModel Login(string userName, string password)
        {
            using (DBCentre db = new DBCentre())
            {
                var user = db.DataContext.Users.FirstOrDefault(p => p.UserName == userName);
                if (user != null)
                {
                    #region 检测验证
                    if (user.Status != (int)Model.Status.Active) throw new ApplicationException("帐号被禁用，请联系本单位的管理员");
                    if (user.Password != password)
                    {
                        //user.LoginTryTimes++;
                        db.DataContext.SaveChanges();
                        throw new ApplicationException("用户名或密码错误");
                    }
                    #endregion

                    user.LastLoginTime = DateTime.Now;
                    //user.LoginTryTimes= 0;
                    db.DataContext.SaveChanges();
                    var ret=Convertor.ConvertTo<UserModel, User>(user);
                    ret.Roles = Convertor.ConvertCollection<RoleModel, Role, RoleCollection>(user.Roles);
                    return ret;
                }
                else
                    throw new ApplicationException("用户名或密码错误");
            }
        }

        public static UserCollection GetUsers(UserQuery sea)
        {
            var result = new UserCollection();
            using (DBCentre db = new DBCentre())
            {
                IQueryable<User> q = db.DataContext.Users;
                if (sea != null)
                {
                    if (!string.IsNullOrEmpty(sea.Key))
                        q = q.Where(p => p.UserName.Contains(sea.Key) || p.RealName.Contains(sea.Key) || p.Mobile == sea.Key);
                }
                var n = q.Count();
                if (n > 0)
                {
                    q = q.OrderByDescending(p => p.ID);
                    if (sea != null && sea.PageSize > 0)
                        q = q.Skip(sea.PageSize * sea.PageIndex);
                    var lst = q.ToList();
                    result = Convertor.ConvertCollection<UserModel, User, UserCollection>(lst);
                    foreach (var model in result)
                    {
                        var d = lst.FirstOrDefault(p => p.ID == model.ID);
                        model.Roles = Convertor.ConvertCollection<RoleModel, Role, RoleCollection>(d.Roles);
                    }
                    result.TotalRecordsCount = n;
                }
            }
            return result;
        }

        #region membership

        public static UserCollection FindUsersInRole(string roleName, string usernameToMatch)
        {
            UserCollection results = new UserCollection();
            using (DBCentre db = new DBCentre())
            {
                IQueryable<User> q = db.DataContext.Users;
                q = q.Where(p => p.UserName.Equals(usernameToMatch, StringComparison.InvariantCultureIgnoreCase));
                q = q.Where(p => p.Roles.Any(o => o.RoleName == roleName));
                var n = q.Count();
                if (n > 0)
                {
                    var lst = q.ToList();
                    results = Convertor.ConvertCollection<UserModel, User, UserCollection>(lst);
                    results.TotalRecordsCount = n;
                }
            }
            return results;
        }

        public static UserCollection GetUsersInRole(string roleName)
        {
            UserCollection results = new UserCollection();
            using (DBCentre dbCentre = new DBCentre())
            {
                IQueryable<User> q = dbCentre.DataContext.Users;
                q = q.Where(p => p.Roles.Any(o => o.RoleName == roleName));
                var n = q.Count();
                if (n > 0)
                {
                    var lst = q.ToList();
                    results = Convertor.ConvertCollection<UserModel, User, UserCollection>(lst);
                    results.TotalRecordsCount = n;
                }
            }
            return results;
        }

        public static bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(oldPassword) && !string.IsNullOrEmpty(newPassword))
            {
                using (DBCentre db = new DBCentre())
                {
                    var dUser = db.DataContext.Users.FirstOrDefault(p => p.UserName == userName);
                    if (dUser != null && dUser.Password == oldPassword)
                    {
                        dUser.Password = newPassword;
                        db.DataContext.SaveChanges();
                        return true;
                    }
                }
            }
            return false;
        }

        public static bool IsUserInRole(string username, string roleName)
        {
            bool result = false;
            using (DBCentre db = new DBCentre())
            {
                result = db.DataContext.Users.Any(p => p.UserName == username && p.Roles.Any(o => o.RoleName == roleName));
            }
            return result;
        }

        public static void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            if (usernames != null && roleNames != null)
            {
                using (DBCentre db = new DBCentre())
                {
                    var roles = db.DataContext.Roles.Where(p => roleNames.Contains(p.RoleName)).ToList();
                    roles.RemoveAll(p => p.Users.Any(o => usernames.Contains(o.UserName)));
                    db.DataContext.SaveChanges();
                }
            }
        }
        #endregion
    }
}
